#include <stdio.h>
#include <string.h>
#include "stm32f10x.h"
#include "./dlt645.h"
#include "../../SYSTEM/utils/utils.h"
#include "../../SYSTEM/usart/usart.h"
#include "../../SYSTEM/bl/bl6552.h"
#include "../../SYSTEM/timer/timer.h"
#define MAX_STOP_TIMER_SECOND 2 // 10秒，现在定时器是5秒
#define MAX_STOP_REPORT_TIME 3
u8 mac_address[6] = {0x12, 0x33, 0x66, 0x77, 0x88, 0x00};
u8 time[6] = {0}; // 秒 分 时 日 月 年
u32 time_counter = 0;
u8 stop_report_count = 0;
u8 stop_timer_count = 0;
u8 is_stop_reporting = 0;

extern Elect_StructDef BL6552_Elect;
// 实际MAC 为 00 88 77 66 33 10-19；

unsigned char bcd_to_hex(unsigned char data)
{
    unsigned char temp;

    temp = ((data >> 4) * 10 + (data & 0x0f));
    return temp;
}
/**
 * Name:    dec2bcd
 * Brief:   十进制转BCD码（目前支持32位数字大小）
 * Input:
 *  @val:   十进制值
 * Output:  BCD码值
 */
uint32_t dec_to_bcd(uint32_t val)
{
    uint32_t data = 0;

    if (val < 100)
    {
        uint8_t byte0 = val % 10;
        uint8_t byte1 = val / 10;
        data = (byte1 << 4) + byte0;
    }
    else if (val < 10000)
    {
        uint8_t byte0 = val % 10;
        uint8_t byte1 = (val / 10) % 10;
        uint8_t byte2 = (val / 100) % 10;
        uint8_t byte3 = (val / 1000) % 10;
        data = (byte3 << 12) +
               (byte2 << 8) +
               (byte1 << 4) + byte0;
    }
    else if (val < 1000000)
    {
        uint8_t byte0 = val % 10;
        uint8_t byte1 = (val / 10) % 10;
        uint8_t byte2 = (val / 100) % 10;
        uint8_t byte3 = (val / 1000) % 10;
        uint8_t byte4 = (val / 10000) % 10;
        uint8_t byte5 = (val / 100000) % 10;
        data = (byte5 << 20) +
               (byte4 << 16) +
               (byte3 << 12) +
               (byte2 << 8) +
               (byte1 << 4) + byte0;
    }
    else if (val < 100000000)
    {
        uint8_t byte0 = val % 10;
        uint8_t byte1 = (val / 10) % 10;
        uint8_t byte2 = (val / 100) % 10;
        uint8_t byte3 = (val / 1000) % 10;
        uint8_t byte4 = (val / 10000) % 10;
        uint8_t byte5 = (val / 100000) % 10;
        uint8_t byte6 = (val / 1000000) % 10;
        uint8_t byte7 = (val / 10000000) % 10;
        data = (byte7 << 28) +
               (byte6 << 24) +
               (byte5 << 20) +
               (byte4 << 16) +
               (byte3 << 12) +
               (byte2 << 8) +
               (byte1 << 4) + byte0;
    }
    return data;
}

/**
 * Name:    _crc
 * Brief:   crc和校验
 * Input:
 *  @msg:   校验数据包
 *  @len:   数据包长度
 * Output:  校验值
 */
int _crc(uint8_t *msg, int len)
{
    uint8_t crc = 0;
    while (len--)
    {
        crc += *msg++;
    }
    return crc;
}

/**
 * Name:    str_to_bcd
 * Brief:   字符串转BCD形式
 * Input:
 *  @str:               要转换的字符串
 *  @bcd_store_address: 转换后的存储地址
 *  @bcd_len:           BCD码总长度
 * Output:  成功0，失败-1
 */
int str_to_bcd(char *str, uint8_t *bcd_store_address, uint16_t bcd_len)
{
    u8 i;
    // 字符串偏移
    int str_pos = bcd_len * 2 - strlen(str);
    // 字符串比BCD码长度长
    if (str_pos < 0)
    {
        return -1;
    }
    memset(bcd_store_address, 0, bcd_len);

    for (i = 0; i < strlen(str); i++)
    {
        if (str[i] >= '0' && str[i] <= '9')
        {
            bcd_store_address[(i + str_pos) / 2] |= (str[i] - '0') << (4 * ((i + 1 + (strlen(str) % 2)) % 2));
        }
        else
        {
            // 当前字符不为数字，返回错误
            return -1;
        }
    }
    return 0;
}
// 打印报文
void dlt645_print_packet(u8 *data, u16 packet_len)
{
    u8 i;
    char buf[255];
    //    u16 count = 0;
    memset(buf, 0, sizeof(buf));
    for (i = 0; i < packet_len; i++)
    {
        WPrint("%02x ", data[i]);
        // sprintf(buf + count * 3, "%02x ", data[i]);
        // // WPrint("%02x ", data[i]);
        if (i != 0 && i % 16 == 0)
        {
            SPrint("\r\n");
        }
    }

    SPrint("\r\n");
}
/// @brief 解析数据
/// @param inBuf
/// @param len
/// @param outBuf
/// @return
u8 dlt645_parse_msg(u8 *inBuf, u16 len, DataPacketFrame *outBuf)
{

    u16 i = 0;
    u16 pos = 0;
    u16 j = 0;
    u8 checkSum = 0;
    if (len < PKT_MIN_LEN)
    {

        return ERR_DATALEN;
    }
    // 前导唤醒帧
    for (j = 0; j < 4; j++)
    {
        if (inBuf[j] == 0xfe)
        {
            i++;
        }
    }
    pos = i;
    // 前导码0x68
    if (inBuf[i] != 0x68 || inBuf[i + 7] != 0x68)
    {
        return ERR_STARTPOS;
    }
    i++;

    // 地址域
    for (j = 0; j < 6; j++)
    {
        outBuf->addr[j] = inBuf[i++];
    }

    i++;
    // 控制码
    outBuf->ctr_Code = inBuf[i++];
    // 数据长度
    outBuf->DataLen = inBuf[i++];

    // 数据
    if (outBuf->ctr_Code == C_2007_CODE_RD)
    {
        for (j = 0; j < 4; j++)
        {
            outBuf->DATA_ID[j] = inBuf[i++] - 0x33; // 原来+33 ，修改为-33 接受应该是-
        }
    }
    else
    {
        for (j = 0; j < outBuf->DataLen; j++)
        {
            outBuf->Data[j] = inBuf[i++] - 0x33;
        }
    }
    // for (j = 0; j < 4; j++)
    // {
    //     outBuf->CIPHER[j] = inBuf[i++] - 0x33;
    // }

    // for (j = 0; j < 4; j++)
    // {
    //     outBuf->operator_Code[j] = inBuf[i++] - 0x33;
    // }

    // 校验和
    for (j = pos; j < i; j++)
    {
        checkSum += inBuf[j++] - 0x33;
    }
    outBuf->CheckSum = inBuf[i];
    // 为什么这儿不做校验
    /*if(checkSum!=inBuf[i]){
    return ERR_CHECKSUM;
    }else{
    outBuf->CheckSum=inBuf[i];
    }*/

    return DATA_OK;
}

/**
 * Name:    dlt645_2007_parsing_data
 * Brief:   DLT645-2007 数据包解析
 * Input:
 *  @code:          标识符
 *  @read_data:     数据包指针
 *  @len:           数据包长度
 *  @real_val:      数据存储地址
 * Output:  数据包长度
 */
// int dlt645_parsing_data(uint32_t code, uint8_t *read_data, uint16_t len, uint8_t *real_val)
// {
//     switch (code)
//     {
//     case DIC_0:
//     case DIC_100:
//     case DIC_200:
//     case DIC_300:
//     case DIC_400:
//     case DIC_10000:
//     case DIC_10100:
//     case DIC_10200:
//     case DIC_10300:
//     case DIC_10400:
//     case DIC_20000:
//     case DIC_20100:
//     case DIC_20200:
//     case DIC_20300:
//     case DIC_20400:
//     case DIC_30000:
//     case DIC_40000:
//     case DIC_50000:
//     case DIC_60000:
//     case DIC_70000:
//     case DIC_80000:
//     case DIC_90000:
//     {
//         dlt645_data_parse_by_format_to_float(read_data, 4, "XXXXXX.XX", real_val);
//         break;
//     }
//     case DIC_2010100:
//     case DIC_2010200:
//     case DIC_2010300:
//     case DIC_20C0100:
//     case DIC_20C0200:
//     case DIC_20C0300:
//     {
//         dlt645_data_parse_by_format_to_float(read_data, 2, "XXX.X", real_val);
//         break;
//     }
//     case DIC_2020100:
//     case DIC_2020200:
//     case DIC_2020300:
//     {
//         dlt645_data_parse_by_format_to_float(read_data, 3, "XXX.XXX", real_val);
//         break;
//     }
//     case DIC_2030000:
//     case DIC_2030100:
//     case DIC_2030200:
//     case DIC_2030300:
//     case DIC_2040000:
//     case DIC_2040100:
//     case DIC_2040200:
//     case DIC_2040300:
//     case DIC_2050000:
//     case DIC_2050100:
//     case DIC_2050200:
//     case DIC_2050300:
//     {
//         dlt645_data_parse_by_format_to_float(read_data, 3, "XX.XXXX", real_val);
//         break;
//     }
//     case DIC_2060000:
//     case DIC_2060100:
//     case DIC_2060200:
//     case DIC_2060300:
//     {
//         dlt645_data_parse_by_format_to_float(read_data, 2, "X.XXX", real_val);
//         break;
//     }
//     case DIC_2800002:
//     {
//         dlt645_data_parse_by_format_to_float(read_data, 2, "XX.XX", real_val);
//         break;
//     }
//     case DIC_4000403:
//     case DIC_5060101:
//     case DIC_7000001:
//     case DIC_7000002:
//         for (uint16_t i = 0; i < len; i++)
//         {
//             real_val[i] = read_data[i] - 0x33;
//         }
//         break;
//     default:
//         for (uint16_t i = 0; i < len; i++)
//         {
//             real_val[i] = ((read_data[i] - 0x33) & 0x0f) + ((read_data[i] - 0x33) >> 4) * 10;
//         }
//         break;
//     }
//     return len;
// }

/**
 * Name:    dlt645_common_check
 * Brief:   645协议接收数据公共部分校验
 * Input:
 *  @msg:   校验数据包
 *  @len:   数据包长度
 *  @addr:  从站地址
 * Output:  校验成功：0，校验失败：-1
 */
int dlt645_common_check(uint8_t *msg, int len)
{
    uint8_t crc = 0;
    // 数据包长度校验
    if (len < 7)
    {
        return -1;
    }
    // 数据帧标志校验
    if (msg[0] != DL645_START_CODE ||
        msg[DL645_ADDR_LEN + 1] != DL645_START_CODE ||
        msg[len - 1] != DL645_STOP_CODE)
    {
        DLT645_LOG("check code error!\n");
        return -1;
    }
    // CRC校验
    crc = _crc(msg, len - 2);
    if (crc != msg[len - 2])
    {
        DLT645_LOG("check crc error!\n");
        return -1;
    }
    // 控制码主从校验,必须主站发出的
    if ((msg[DL645_CONTROL_POS] & C_TD_MASK) == 0)
    {
        DLT645_LOG("check control direction error!\n");
        return -1;
    }
    // 控制码应答校验
    //  if ((msg[DL645_CONTROL_POS] & C_ACK_MASK) == (C_ACK_ERR << C_ACK_POS))
    //  {
    //      DLT645_LOG("check ACK error!\n");
    //      return msg[len - 3];
    //  }
    // 从站地址校验 ,地址不比较
    //  if (memcmp(msg + 1, addr, 6) != 0)
    //  {
    //      return -1;
    //  }

    return 0;
}

/**
 * Name:    dlt645_recv_check
 * Brief:   DLT645-2007 数据校验
 * Input:
 *  @msg:   校验数据包
 *  @len:   数据包长度
 * Output:  数据操作码 code  FFFFFFFF表示错误
 */
uint32_t dlt645_recv_check(uint8_t *msg, int len)
{
    uint32_t code = 0;
    uint8_t *code_buf = msg + DL645_DATA_POS;
    uint8_t i = 0;

    if (dlt645_common_check(msg, len) < 0)
    {
        return CODE_ERR;
    }
    // if (msg[DL645_CONTROL_POS] == 0x94)
    //     return 0;

    for (i = 0; i < 4; i++)
    {
        code_buf[i] -= 0x33;
    }
    memcpy(&code, code_buf, 4);

    // if (*((uint32_t *)(msg + DL645_DATA_POS)) != code)
    //     return -1;

    return code;
}

void dlt645_sendToHal(u8 *buf, u16 len)
{
    WPrint("send msg: %d\r\n", len);
    dlt645_print_packet(buf, len);
    UART2_SendData(buf, len);
}

/// @brief
/// @param sendData
void dlt645_sendMsg(DataPacketFrame *sendData)
{
    u8 i = 0;
    u8 crc = 0;
    uint8_t send_buf[DL645_RESP_LEN];
    memset(send_buf, 0, sizeof(send_buf));
    send_buf[0] = 0x68;
    memcpy(send_buf + 1, sendData->addr, DL645_ADDR_LEN);
    send_buf[7] = 0x68;
    send_buf[DL645_CONTROL_POS] = sendData->ctr_Code;
    send_buf[DL645_LEN_POS] = sendData->DataLen;
    for (i = 0; i < sendData->DataLen; i++)
    {
        send_buf[DL645_DATA_POS + i] = sendData->Data[i] + 0x33;
    }

    crc = _crc(send_buf, DL645_DATA_POS + sendData->DataLen);
    send_buf[DL645_DATA_POS + sendData->DataLen] = crc;
    send_buf[DL645_DATA_POS + sendData->DataLen + 1] = 0x16;

    dlt645_sendToHal(send_buf, DL645_DATA_POS + sendData->DataLen + 2);
}

u8 CaculateWeekDay(int y, int m, int d)
{
    int iWeek;
    if (m == 1 || m == 2)
    {
        m += 12;
        y--;
    }
    iWeek = ((d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400 + 1) % 7 + 7) % 7;
    // WPrint("week:%d\r\n",iWeek);
    return iWeek;
}

// 获取当前时间
void getCurrentTime(u8 *dataTime)
{

    u32 tc = getTimeCount();
    u32 ft = standard_to_stamp(time);

    // WPrint("tc:%d,fc:%d\r\n", tc, ft);
    tc = ft + tc;
    stamp_to_standard(tc, dataTime);
}

void dlt645_copydata(DataPacketFrame *d, u32 s, u8 len)
{
    u32 v = s;
    d->DataLen = len + 4; // 前面有4个字节

    v = dec_to_bcd(v);
    //  WPrint("BCD: %x\r\n", v);
    memcpy(d->Data + 4, &v, len);
}

/// @brief 处理读数据消息
/// @param msgData
void dlt645_handleReadData(DataPacketFrame *msgData)
{
    u8 i = 0;
    u8 d[6] = {0};
    u8 s[6] = {0};
    u32 v = 0;
    u32 di = 0xffffffff;
    DataPacketFrame sendData;
    memcpy(sendData.addr, msgData->addr, 6);

    // 这儿本身MAC就是BCD码不需要转换
    sendData.ctr_Code = 0x91;
    memcpy(&di, msgData->DATA_ID, 4);
    WPrint("di: %x\r\n", di);
    memcpy(sendData.Data, msgData->DATA_ID, 4);
    switch (di)
    {

    case 0x00000000:
        // 读组合总能量
        di = BL65XX_GetTotalEnergy();
        WPrint("EnergyP: %d\r\n", di);
        dlt645_copydata(&sendData, di, 4);
        break;
    case 0x00010000:
        // 读正向有功总电能
        di = BL65XX_GetTotalEnergy();
        WPrint("EnergyP: %d\r\n", di);
        dlt645_copydata(&sendData, di, 4);
        break;

    case 0x00020000:
        // 反向有功总电能
        WPrint("EnergyP_N: %d\r\n", BL6552_Elect.EnergyP_N);
        dlt645_copydata(&sendData, BL6552_Elect.EnergyP_N, 4);
        break;
    case 0x00150000:
        // A 相正向有功电能
        WPrint("EnergyP_P_A: %d\r\n", BL6552_Elect.EnergyP_P_A);
        dlt645_copydata(&sendData, BL6552_Elect.EnergyP_P_A, 4);
        break;
    case 0x00160000:
        // A 相反向有功电能
        WPrint("EnergyP_N_A: %d\r\n", BL6552_Elect.EnergyP_N_A);
        dlt645_copydata(&sendData, BL6552_Elect.EnergyP_N_A, 4);
        break;
    case 0x00290000:
        // B 相正向有功电能
        WPrint("EnergyP_P_B: %d\r\n", BL6552_Elect.EnergyP_P_B);
        dlt645_copydata(&sendData, BL6552_Elect.EnergyP_P_B, 4);
        break;
    case 0x002A0000:
        // B 相反向有功电能
        WPrint("EnergyP_N_B: %d\r\n", BL6552_Elect.EnergyP_N_B);
        dlt645_copydata(&sendData, BL6552_Elect.EnergyP_N_B, 4);
        break;
    case 0x003D0000:
        // C 相正向有功电能
        WPrint("EnergyP_P_C: %d\r\n", BL6552_Elect.EnergyP_P_C);
        dlt645_copydata(&sendData, BL6552_Elect.EnergyP_P_C, 4);
        break;
    case 0x003E0000:
        // C 相反向有功电能
        WPrint("EnergyP_N_C: %d\r\n", BL6552_Elect.EnergyP_N_C);
        dlt645_copydata(&sendData, BL6552_Elect.EnergyP_N_C, 4);
        break;
    case 0x02010100: // vA  XXX.X
        WPrint("VA_RMS: %d\r\n", BL6552_Elect.VA_RMS);
        dlt645_copydata(&sendData, BL6552_Elect.VA_RMS / 10, 2);
        break;
    case 0x02010200: // V b  XXX.X
        WPrint("VB_RMS: %d\r\n", BL6552_Elect.VB_RMS);
        dlt645_copydata(&sendData, BL6552_Elect.VB_RMS / 10, 2);
        break;
    case 0x02010300: // VC   XXX.X
        WPrint("VC_RMS: %d\r\n", BL6552_Elect.VC_RMS);
        dlt645_copydata(&sendData, BL6552_Elect.VC_RMS / 10, 2);
        break;

    case 0x02020100: // IA XXX.XX
        WPrint("IA_RMS: %d\r\n", BL6552_Elect.IA_RMS);
        dlt645_copydata(&sendData, BL6552_Elect.IA_RMS, 3);
        break;
    case 0x02020200: // IB XXX.XX
        WPrint("IB_RMS: %d\r\n", BL6552_Elect.IB_RMS);
        dlt645_copydata(&sendData, BL6552_Elect.IB_RMS, 3);
        break;
    case 0x02020300: // IC XXX.XX
        WPrint("IC_RMS: %d\r\n", BL6552_Elect.IC_RMS);
        dlt645_copydata(&sendData, BL6552_Elect.IC_RMS, 3);
        break;
    case 0x04000101: // date: yymmddww
        if (time[5] == 0)
        {
            // 没有同步时钟直接不回复
            return;
        }
        getCurrentTime(d);
        //  WPrint("read time: %02d-%02d-%02d %02d:%02d:%02d \r\n ", d[5], d[4], d[3], d[2], d[1], d[0]);
        s[3] = dec_to_bcd(d[5]); // yy
        s[2] = dec_to_bcd(d[4]); // mm
        s[1] = dec_to_bcd(d[3]); // dd
        s[0] = dec_to_bcd(CaculateWeekDay(d[5] + 2000, d[4], d[3]));
        sendData.DataLen = 8;
        memcpy(sendData.Data + 4, s, 4);
        break;
    case 0x04000102: // date: yymmddww
        if (time[5] == 0)
        {
            // 没有同步时钟直接不回复
            return;
        }
        getCurrentTime(d);
        WPrint("read time: %02d-%02d-%02d %02d:%02d:%02d \r\n ", d[5], d[4], d[3], d[2], d[1], d[0]);
        for (i = 0; i < 3; i++)
        {
            s[i] = dec_to_bcd(d[i]);
        }
        sendData.DataLen = 8;
        memcpy(sendData.Data + 4, s, 4);
        break;
    case 0x1d000001:       // 读停电次数
    case 0x03110000:       // 南网标准，停电次数
        stop_get_total(d); // 没有返回权0
        WPrint("total: %02X %02X %02X \r\n ", d[2], d[1], d[0]);
        for (i = 0; i < 3; i++)
        {
            s[i] = dec_to_bcd(d[i]);
        }
        sendData.DataLen = 8;
        memcpy(sendData.Data + 4, s, 4);
        break;

    case 0x1d000101:             // 读上一次停电记录
    case 0x03110101:             // 南网标准，读上一次停电记录
        stop_get_last_record(d); // 没有返回权0
        WPrint("last record time: %02d-%02d-%02d %02d:%02d:%02d \r\n ", d[5], d[4], d[3], d[2], d[1], d[0]);
        for (i = 0; i < 6; i++)
        {
            s[i] = dec_to_bcd(d[i]);
        }
        sendData.DataLen = 12;
        memcpy(sendData.Data + 4, s, 6);
        break;
    case 0x0400040F: // 北斗
        WPrint("beidou");
        v = 319381;            // 经度
        sendData.DataLen = 15; // 4+4+3
        v = dec_to_bcd(v);
        memcpy(sendData.Data + 4, &v, 4);
        v = 1187408; // 纬度
        v = dec_to_bcd(v);
        memcpy(sendData.Data + 8, &v, 4);
        v = 0; // 高度
        v = dec_to_bcd(v);
        memcpy(sendData.Data + 12, &v, 4);
        break;
    case 0x04101001: // 拓扑
        WPrint("toplogy");
        d[0] = 0x00;
        d[1] = 0x11;
        d[2] = 0x21;
        d[3] = 0x31;
        d[4] = 0x41;
        d[5] = 0x51;
        for (i = 0; i < 6; i++)
        {
            s[i] = dec_to_bcd(d[i]);
        }
        sendData.DataLen = 16; // 4+12
        memcpy(sendData.Data + 4, s, 6);
        d[5] = 0x52;
        for (i = 0; i < 6; i++)
        {
            s[i] = dec_to_bcd(d[i]);
        }        
        memcpy(sendData.Data + 10, s, 6);
        break;
    default:
        return;
    };

    dlt645_sendMsg(&sendData);
}

/// @brief 读通讯地址
/// @param msgData
void dlt645_handleReadAddress(DataPacketFrame *msgData)
{
    u8 i = 0;
    DataPacketFrame sendData;

    for (i = 0; i < 6; i++)
    {
        if (msgData->addr[i] != 0xAA)
        {
            DLT645_LOG("read address is not AAAAAAAA");
            return;
        }
    }

    // 这儿本身MAC就是BCD码不需要转换
    sendData.ctr_Code = 0x93;
    memcpy(sendData.addr, mac_address, 6);
    sendData.DataLen = 6;
    memcpy(sendData.Data, mac_address, 6);
    dlt645_sendMsg(&sendData);
}

/// @brief 广播校时
/// @param msgData
void dlt645_handleValidTime(DataPacketFrame *msgData)
{
    u8 i = 0;
    // DataPacketFrame sendData;

    for (i = 0; i < 6; i++)
    {
        if (msgData->addr[i] != 0x99)
        {
            DLT645_LOG("read address is not 9999");
            return;
        }
    }
    for (i = 0; i < 6; i++)
    {
        time[i] = bcd_to_hex(msgData->Data[i]);
    }

    // 不需要回复，更新时间

    WPrint("current time: %02d-%02d-%02d %02d:%02d:%02d \r\n ", time[5], time[4], time[3], time[2], time[1], time[0]);
    resetTimeCount();
}

void print_msg(DataPacketFrame msgData)
{
    WPrint("ctl code :%d", msgData.ctr_Code);
}

void dlt645_handleStopConfirm()
{
    // 收到停止报文，不需要校验直接停止发送
    stop_report_count = 0;
    stop_timer_count = 0;
    is_stop_reporting = 0;
}

/**
 * Name:    dlt645_receive_msg
 * Brief:   645协议调用底层接收数据
 * Input:
 *  @msg:       数据包存储地址
 *  @len:       最大接收长度
 *  @code:      数据标识
 * Output:  接收成功：0，接收失败：-1
 */
void dlt645_receive_msg(uint8_t *msg, uint16_t len)
{
    DataPacketFrame msgData;
    u8 ctl_code = 0;
    u8 rst = 0;
    // uint8_t read_buf[4];
    // uint32_t code = CODE_ERR;
    memset(&msgData, 0, sizeof(DataPacketFrame));
    // dlt645_print_packet(msg, len);
    rst = dlt645_parse_msg(msg, len, &msgData);
    if (rst != DATA_OK)
    {
        // WPrint("prase message error:%d", rst);
        return;
    }
    ctl_code = msgData.ctr_Code & 0x1F;

    WPrint("#process control code: %2X \r\n", ctl_code);
    // 根据控制码做处理
    switch (ctl_code)
    {
    case C_2007_CODE_RD: // 读数据
        dlt645_handleReadData(&msgData);
        return;
    case C_2007_CODE_RDM: // 读后续数据，@todo 后续实现
        // dlt645_handleReadNextData();
        return;

    case C_2007_CODE_RDA: // 读通信地址
        dlt645_handleReadAddress(&msgData);
        return;

    case C_2007_CODE_WR: // 写数据  @todo 后续实现
        // dlt645_handleWriteData();
        return;
    case C_2007_CODE_WRA: // 写通信地址
        // dlt645_handleWriteAddress();
        return;
    case C_2007_CODE_BRC: // 广播校时
        dlt645_handleValidTime(&msgData);
    case C_2007_CODE_DJ:  // 冻结
    case C_2007_CODE_BR:  // 更改通信速率
    case C_2007_CODE_PD:  // 修改密码
    case C_2007_CODE_XL:  // 最大需量清零
    case C_2007_CODE_DB:  // 电表清零
    case C_2007_CODE_MSG: // 事件清零
                          // @TODO 后续实现
        return;
    case C_2017N_CODE_CONFIRM: // 上报状态响应
        dlt645_handleStopConfirm();
    default:
        break;
    }
    return;
}

/**
 * 南网645协议主动上报事件
 */
void dlt645_sendStopEventMsg(u8 isTimer)
{
    u8 i = 0;
    u8 d[12] = {0};
    u8 s[12] = {0};
    DataPacketFrame sendData = {0};

    if (isTimer)
    {
        // 来自定时器
        if (stop_timer_count < MAX_STOP_TIMER_SECOND)
        {
            stop_timer_count++;
            return;
        }
        else
        {
            stop_timer_count = 0;
        }
    }
    else
    {
        stop_timer_count = 0;
        is_stop_reporting = 1;
    }

    memcpy(sendData.addr, mac_address, 6);
    sendData.ctr_Code = 0x86;
    // 置停电标记位
    d[8] = 0x20;
    for (i = 0; i < 12; i++)
    {
        s[i] = dec_to_bcd(d[i]);
    }

    sendData.DataLen = 12 + 4;
    // event code 04 00 15 01
    sendData.Data[3] = 0x04;
    sendData.Data[2] = 0x00;
    sendData.Data[1] = 0x15;
    sendData.Data[0] = 0x01;
    memcpy(sendData.Data + 4, s, 12);

    if (is_stop_reporting)
    {
        dlt645_sendMsg(&sendData);
        SPrint("------>>>>send stop event...\r\n");
    }

    // 置事件定时器
    stop_report_count++;
    if (stop_report_count >= MAX_STOP_REPORT_TIME)
    {
        is_stop_reporting = 0;
    }
}

void dlt645_restroeProcess()
{
    stop_report_count = 0;
    stop_timer_count = 0;
    is_stop_reporting = 0;
}

// void receive_packet(char *data, u16 packet_len)
// {
//     DataPacketFrame msg;
//     dlt645_print_packet(data, packet_len);
//     parse_packet(data, packet_len, &msg);
// }
